//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>
#include <nu_api.h>
#include <rtc.h>
//#define _DBGRTC

#define MAXYEAR     (2037)
static nu_rtcDriver *g_pNURTCDriver = NULL;
CRTC *g_pRTC = NULL;
EXTERN SystemTime g_systemTime;
int g_ostDelta = 0;

typedef struct{
    UInt8   second;
    UInt8   minute;
    UInt8     hour;
    UInt8      day;
    UInt8    month;
    UInt8     year;
    UInt8  weekday;
    UInt8 hourMode; /* hour mode - [0-1] - [12-24]*/
    UInt8 hourType; /* AM or PM [0-1] [AM-PM] */
} RTCATime;
//RTCATime rat;

typedef struct {
    UInt8 uYear;    //0~99
    UInt8 uMonth;   //1~12
    UInt8 uDay;     //1~31
    UInt8 uHour;    //0~23
    UInt8 uMinute;  //0~59
    UInt8 uSecond;  //0~59
    UInt8 uWeekDay; //0~6
    UInt8 Reserved2;
}PackTime;

INLINE UInt32 RTCTimeToSeconds(const PackTime *pRTCTime)
{
    assert(pRTCTime);

    int nMonth  = pRTCTime->uMonth;
    int nYear   = pRTCTime->uYear+2000;
    int nDate   = pRTCTime->uDay;
    nMonth -= 2;            // 1..12 -> 11,12,1..10
    if (0 >= nMonth) {
        nMonth  += 12;      // Puts Feb last since it has leap day
        nYear   -= 1;
    }

    UInt32 uSeconds = (uint_t)(nYear / 4 - nYear / 100 + nYear / 400
            + 367 * nMonth / 12 + nDate) + nYear * 365 - 719499;

    uSeconds = uSeconds * 24 + pRTCTime->uHour;    // now have hours
    uSeconds = uSeconds * 60 + pRTCTime->uMinute;  // now have minutes
    uSeconds = uSeconds * 60 + pRTCTime->uSecond;  // finally seconds

    return uSeconds;
}

INLINE void SecondsToRTCTime(uint32_t uSeconds, RTCTime *pRTCTime)
{
    assert(pRTCTime);

#define SECONDS_PER_DAY     (3600 * 24)

    uint32_t uHoursMinutesSeconds = uSeconds % SECONDS_PER_DAY;
    pRTCTime->uHours    = uHoursMinutesSeconds / 3600;
    pRTCTime->uMinutes  = (uHoursMinutesSeconds % 3600) / 60;
    pRTCTime->uSeconds  = uHoursMinutesSeconds % 60;

#define IS_LEAPYEAR(y)      \
    (((0 == (y) % 4) && (0 != (y) % 100)) || (0 == (y) % 400))
#define DAYS_PER_YEAR(y)    (IS_LEAPYEAR(y)? 366u : 365u)

    uint32_t uDays = uSeconds / SECONDS_PER_DAY;
    uint32_t uYear;
    for (uYear = 1970; uDays >= DAYS_PER_YEAR(uYear); uYear++) {
        uDays -= DAYS_PER_YEAR(uYear);
    }
    pRTCTime->uYear = uYear;

    uint32_t uDaysPerMonth[12] = {
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };

#define DAYS_PER_MONTH(m)   (uDaysPerMonth[(m) - 1])
    if (IS_LEAPYEAR(uYear)) DAYS_PER_MONTH(2) = 29;

    uint32_t uMonth;
    for (uMonth = 1; uDays >= DAYS_PER_MONTH(uMonth); uMonth++) {
        uDays -= DAYS_PER_MONTH(uMonth);
    }
    pRTCTime->uMonth = uMonth;

    pRTCTime->uDate = uDays + 1;
}

unsigned long _GetElapsed()
{
    PackTime t;
    RTCATime rtcTime;

	g_pNURTCDriver->GetRTCTime(&rtcTime);
	t.uYear = rtcTime.year;
	t.uMonth = rtcTime.month;
	t.uDay = rtcTime.day;
	t.uHour = rtcTime.hour;
	t.uMinute = rtcTime.minute;
	t.uSecond = rtcTime.second;
    t.uWeekDay = rtcTime.weekday;

    return RTCTimeToSeconds(&t) - g_ostDelta;
}

void UpdataRTCTime (UInt32 Elapsed)
{
    g_ostDelta += _GetElapsed() - Elapsed;
    DzSyncSystemTime();//Sync os time

    PackTime t;
    RTCATime rtcTime;

	g_pNURTCDriver->GetRTCTime(&rtcTime);
	t.uYear = rtcTime.year;
	t.uMonth = rtcTime.month;
	t.uDay = rtcTime.day;
	t.uHour = rtcTime.hour;
	t.uMinute = rtcTime.minute;
	t.uSecond = rtcTime.second;
    t.uWeekDay = rtcTime.weekday;

    EmIsrParameter Param;

    memset(&Param, 0, sizeof(EmIsrParameter));

    memcpy(&Param, &t, sizeof(PackTime));
    EmPostEventByIsr(114, &Param);//send time change event
}

ECode setRTCTime(int h, int m, int s)
{
    if ((h < 0 || h > 23) || (m < 0 || m > 59) || (s < 0 || s > 59)) {
        return E_INVALID_ARGUMENT;
    }

    UInt32 Elapsed;
	RTCATime rat;
	UInt32 ret = g_pNURTCDriver->GetRTCTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}

	if (rat.weekday > 6 || rat.month >12 || rat.year > 99 || rat.day > 31) {
		rat.weekday = (UInt8)0;
		rat.month = (UInt8)1;
		rat.year = (UInt8)8;
		rat.day = (UInt8)1;
	}
	rat.hour = (UInt8)h;
	rat.minute = (UInt8)m;
	rat.second = (UInt8)s;
	rat.hourMode = 1;
	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	  rat.hourType = 0;
	}

    Elapsed = _GetElapsed();
	ret = g_pNURTCDriver->SetRTCTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}
	UpdataRTCTime(Elapsed);
    return NOERROR;
}

UInt32 CaculateWeekDay( // using kslarsen formula
    /* [in] */ UInt32 y,
    /* [in] */ UInt32 m,
    /* [in] */ UInt32 d)
{
    if (m == 1 || m == 2) {
        m += 12;
        y--;
    }
    return (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400 + 1) % 7;
}


ECode setRTCDate (int w,int y,int m,int d)
{
    if ((w < 0 || w > 6) || (y < 0 || y > 99) ||
        (m < 1 || m > 12) || (d < 1 || d > 31)) {
        return E_INVALID_ARGUMENT;
    }

    UInt32 Elapsed;
	RTCATime rat;
	UInt32 ret;

	ret = g_pNURTCDriver->GetRTCTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}

	rat.month = (UInt8)m;
	rat.year = (UInt8)y;
	rat.day = (UInt8)d;
	if (rat.year > 99) {
   		rat.year = rat.year % 100;
   	}
   	rat.weekday = CaculateWeekDay(rat.year + 2000, rat.month, rat.day);

	if (rat.hour > 23 || rat.minute > 59 || rat.second > 59) {
		rat.hour = (UInt8)0;
		rat.minute = (UInt8)0;
		rat.second = (UInt8)0;
	}
	rat.hourMode = 1;
	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	    rat.hourType = 0;
	}

    Elapsed = _GetElapsed();
	ret = g_pNURTCDriver->SetRTCTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}
	UpdataRTCTime(Elapsed);
    return NOERROR;
}

ECode setRTCAtime(int h,int m,int s)
{
    if ((h < 0 || h > 23) || (m < 0 || m > 59) || (s < 0 || s > 59)) {
        return E_INVALID_ARGUMENT;
    }

	RTCATime rat;
	UInt32 ret;
	ret = g_pNURTCDriver->GetAlarmTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}

	if (rat.weekday > 6) rat.weekday = (UInt8)0;
	if (rat.month >12 ) rat.month = (UInt8)1;
	if (rat.year > 99) rat.year = (UInt8)8;
	if (rat.day > 31)  rat.day = (UInt8)1;

	rat.hour = (UInt8)h;
	rat.minute = (UInt8)m;
	rat.second = (UInt8)s;
	rat.hourMode = 1;

	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	    rat.hourType = 0;
	}

	ret = g_pNURTCDriver->SetAlarmTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}
//	int ret = g_pNURTCDriver->GetAlarmTime(&rat);
//	if (0 != ret) {
//		kprintf("get ERROR");
//	}

	return NOERROR;
}

ECode setRTCAdate(int w,int y,int m,int d)
{
    if ((w < 0 || w > 6) || (y < 0 || y > 99) ||
        (m < 1 || m > 12) || (d < 1 || d > 31)) {
        return E_INVALID_ARGUMENT;
    }

	RTCATime rat;
	UInt32 ret;

	ret = g_pNURTCDriver->GetAlarmTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}

	rat.month = (UInt8)m;
	rat.year = (UInt8)y;
	rat.day = (UInt8)d;

    if (rat.year > 99) {
   		rat.year = rat.year % 100;
   	}

    rat.weekday = CaculateWeekDay(rat.year + 2000, rat.month, rat.day);

	if (rat.hour > 23) rat.hour = (UInt8)0;
	if (rat.minute > 59) rat.minute = (UInt8)0;
	if (rat.second > 59) rat.second = (UInt8)0;

	rat.hourMode = 1;
	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	    rat.hourType = 0;
	}

	ret = g_pNURTCDriver->SetAlarmTime(&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}

	return NOERROR;
}

ECode setAlarmDateTime(int * p)
{
    RTCATime rat;
	UInt32 ret;

	if ((p[0] < 0 || p[0] > 6) || (p[1] < 0 || p[1] > 99) ||
        (p[2] < 1 || p[2] > 12) || (p[3] < 1 || p[3] > 31) ||
        (p[4] < 0 || p[4] > 23) || (p[5] < 0 || p[5] > 59) ||
        (p[6] < 0 || p[6] > 59)) {
        return E_INVALID_ARGUMENT;
    }

	rat.year = (UInt8)p[1];
    rat.month = (UInt8)p[2];
	rat.day = (UInt8)p[3];

    if (rat.year > 99) {
   		rat.year = rat.year % 100;
   	}
    rat.weekday = CaculateWeekDay(rat.year + 2000, rat.month, rat.day);

    rat.hour = (UInt8)p[4];
	rat.minute = (UInt8)p[5];
	rat.second = (UInt8)p[6];

    rat.hourMode = 1;
	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	    rat.hourType = 0;
	}

	ret = g_pNURTCDriver->SetAlarmTime(&rat);
	if (0 != ret) {
		kprintf("alarm fail %S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}
	kprintf("%d, %d, %d, %d, %d, %d\n", rat.year, rat.month, rat.day, rat.hour, rat.minute, rat.second);
    kprintf("set alarm OK!\n");
	return NOERROR;
}

ECode setRTCdatetime(SystemTime *pSystemTime)
{
	RTCTime t;
	RTCATime rat;
	UInt32 Elapsed;

    SecondsToRTCTime(pSystemTime->seconds, &t);

    memset(&rat, 0, sizeof(RTCATime));

    rat.second = t.uSeconds;
    rat.minute = t.uMinutes;
    rat.hour   = t.uHours;
    rat.day    = t.uDate;
    rat.month  = t.uMonth;

   	if (t.uYear > 99) {
   		rat.year = t.uYear % 100;
   	}

    rat.weekday = CaculateWeekDay(rat.year + 2000, rat.month, rat.day);

    rat.hourMode = 1;
	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	    rat.hourType = 0;
	}
    Elapsed = _GetElapsed();
    UInt32 ret;
    ret = g_pNURTCDriver->SetRTCTime((void *)&rat);
	if (0 != ret) {
		kprintf("%S, %d \n", __FILE__, __LINE__);
		return E_ACCESS_DENIED;
	}

    UpdataRTCTime(Elapsed);

    return NOERROR;
}

ECode DisableRTCAlarm()
{
	UInt32 ret = g_pNURTCDriver->UnSetAlarm();
    if (0 != ret) return E_ACCESS_DENIED;
    kprintf("Disable Alarm OK\n");
    return NOERROR;
}

ECode EnableRTCAlarm ()
{
	RTCATime rat;
	int ret;
	ret = g_pNURTCDriver->GetAlarmTime(&rat);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}

    rat.hourMode = 1;
	if (rat.hour > 12) {
	    rat.hourType = 1;
	} else {
	    rat.hourType = 0;
	}

    rat.weekday = CaculateWeekDay(rat.year, rat.month, rat.day);

	ret = g_pNURTCDriver->SetAlarmTime(&rat);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}
	return NOERROR;
}

ECode GetRTCTimeInfo(MemoryBuf * pOutData)
{
	if (pOutData == NULL || pOutData->GetCapacity() < 12) {
    	return E_INVALID_ARGUMENT;
    }
	RTCATime rtcTime;
	UInt32 ret = g_pNURTCDriver->GetRTCTime(&rtcTime);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}

	UInt32 hour = rtcTime.hour;
	UInt32 minute = rtcTime.minute;
	UInt32 second = rtcTime.second;
	pOutData->Copy((Byte *)&hour, 4);
    pOutData->Append((Byte *)&minute, 4);
    pOutData->Append((Byte *)&second, 4);
    pOutData->SetUsed(12);
//    kprintf("------------------------time\n");
//    kprintf("%d, %d, %d\n", hour, minute, second);

    return NOERROR;
}

ECode GetRTCDateInfo(MemoryBuf * pOutData)
{
	if (pOutData == NULL || pOutData->GetCapacity() < 16) {
    	return E_INVALID_ARGUMENT;
    }
	RTCATime rtcTime;
	UInt32 ret = g_pNURTCDriver->GetRTCTime(&rtcTime);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}

	UInt32 weekday = rtcTime.weekday;
	UInt32 year = rtcTime.year;
	UInt32 month = rtcTime.month;
	UInt32 day = rtcTime.day;
	pOutData->Copy((Byte *)&weekday, 4);
    pOutData->Append((Byte *)&year, 4);
    pOutData->Append((Byte *)&month, 4);
    pOutData->Append((Byte *)&day, 4);
    pOutData->SetUsed(16);

//	kprintf("------------------------Adate\n");
//  kprintf("%d, %d, %d, %d\n", weekday, year, month, day);
    return NOERROR;
}

ECode GetRTCDateTime(MemoryBuf *pOutData)
{
    RTCATime rat;
    UInt32 ret = g_pNURTCDriver->GetRTCTime(&rat);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}
	UInt32 weekday = rat.weekday;
	UInt32 year = rat.year;
	UInt32 month = rat.month;
	UInt32 day = rat.day;
	UInt32 hour = rat.hour;
	UInt32 minute = rat.minute;
	UInt32 second = rat.second;

    pOutData->Copy((Byte *)&weekday, 4);
    pOutData->Append((Byte *)&year, 4);
    pOutData->Append((Byte *)&month, 4);
    pOutData->Append((Byte *)&day, 4);
    pOutData->Append((Byte *)&hour, 4);
    pOutData->Append((Byte *)&minute, 4);
    pOutData->Append((Byte *)&second, 4);
    pOutData->SetUsed(28);

    return NOERROR;
}

ECode GetRTCAlarmTimeInfo(MemoryBuf * pOutData)
{
	if (pOutData == NULL || pOutData->GetCapacity() < 12) {
    	return E_INVALID_ARGUMENT;
    }
	RTCATime rat;

	UInt32 ret = g_pNURTCDriver->GetAlarmTime(&rat);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}
	UInt32 hour = rat.hour;
	UInt32 minute = rat.minute;
	UInt32 second = rat.second;
	pOutData->Copy((Byte *)&hour, 4);
    pOutData->Append((Byte *)&minute, 4);
    pOutData->Append((Byte *)&second, 4);
    pOutData->SetUsed(12);
//	kprintf("------------------------Atime\n");
//  kprintf("%d, %d, %d\n", hour, minute, second);
    return NOERROR;
}

ECode GetRTCAlarmDateInfo(MemoryBuf * pOutData)
{
	if (pOutData == NULL || pOutData->GetCapacity() < 16) {
    	return E_INVALID_ARGUMENT;
    }
	RTCATime rat;

	UInt32 ret = g_pNURTCDriver->GetAlarmTime(&rat);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}

	UInt32 weekday = CaculateWeekDay(rat.year, rat.month, rat.day);
	UInt32 year = rat.year;
	UInt32 month = rat.month;
	UInt32 day = rat.day;
	pOutData->Copy((Byte *)&weekday, 4);
    pOutData->Append((Byte *)&year, 4);
    pOutData->Append((Byte *)&month, 4);
    pOutData->Append((Byte *)&day, 4);
    pOutData->SetUsed(16);
//	kprintf("------------------------date\n");
//  kprintf("%d, %d, %d, %d\n", weekday, year, month, day);
    return NOERROR;
}

ECode GetAlarmDateTime(MemoryBuf * pOutData)
{
    RTCATime rat;
    UInt32 ret = g_pNURTCDriver->GetAlarmTime(&rat);
	if (0 != ret) {
		return E_ACCESS_DENIED;
	}
	UInt32 weekday = CaculateWeekDay(rat.year, rat.month, rat.day);
	UInt32 year = rat.year;
	UInt32 month = rat.month;
	UInt32 day = rat.day;
	UInt32 hour = rat.hour;
	UInt32 minute = rat.minute;
	UInt32 second = rat.second;

    pOutData->Copy((Byte *)&weekday, 4);
    pOutData->Append((Byte *)&year, 4);
    pOutData->Append((Byte *)&month, 4);
    pOutData->Append((Byte *)&day, 4);
    pOutData->Append((Byte *)&hour, 4);
    pOutData->Append((Byte *)&minute, 4);
    pOutData->Append((Byte *)&second, 4);
    pOutData->SetUsed(28);

    return NOERROR;
}

ECode CRTC::Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode  CRTC::Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf &buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode CRTC::Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf &inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    switch(nControlCode) {
    	case 0://Enable alarm
    	{
//    	    kprintf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Enable alarm\n");
//			return EnableRTCAlarm();
    	    return NOERROR;
    	}
    	case 1://Disable alarm
    	{
    		return DisableRTCAlarm();
    	}
    	case 2://get rtc time info
    	{
    		return GetRTCTimeInfo(pOutBuffer);
    	}
    	case 3://get rtc date info
    	{
    		return GetRTCDateInfo(pOutBuffer);
    	}
    	case 4://get rtc alarm time info
    	{
    		return GetRTCAlarmTimeInfo(pOutBuffer);
    	}
    	case 5://get rtc alarm date info
    	{
    		return GetRTCAlarmDateInfo(pOutBuffer);
    	}
    	case 6://set rtc time info
    	{
    	    if (inBuffer.GetCapacity() < 12) return E_INVALID_ARGUMENT;
            int * p = (int *)inBuffer.GetPayload();
    	    return setRTCTime(p[0], p[1], p[2]);
    	    break;
    	}
    	case 7://set rtc date info
    	{
			if (inBuffer.GetCapacity() < 16) return E_INVALID_ARGUMENT;
            int * p = (int *)inBuffer.GetPayload();
            return setRTCDate(p[0], p[1], p[2], p[3]);
    	    break;
    	}
        case 8://set rtc alarm time
        {
			if (inBuffer.GetCapacity() < 12) return E_INVALID_ARGUMENT;
            int * p = (int *)inBuffer.GetPayload();
            return setRTCAtime(p[0], p[1], p[2]);
        }
        case 9://set rtc alarm date
        {
			if (inBuffer.GetCapacity() < 16) return E_INVALID_ARGUMENT;
            int * p = (int *)inBuffer.GetPayload();
            return setRTCAdate(p[0], p[1], p[2], p[3]);
        }
        case 10://set rtc date & time
        {
        	if (inBuffer.GetCapacity() < (int)sizeof(SystemTime)) {
        		return E_INVALID_ARGUMENT;
        	}
        	SystemTime * pSystemTime = (SystemTime *)inBuffer.GetPayload();
        	if (pSystemTime->seconds & 0x80000000) {
                return E_INVALID_ARGUMENT;
        	}
            return setRTCdatetime(pSystemTime);
            break;
        }
        case 11://Sync os time
        {
            DzSyncSystemTime();
            break;
        }
        case 12://Get elapse seconds
        {
            if (pOutBuffer == NULL || pOutBuffer->GetCapacity() < 4) {
                return E_INVALID_ARGUMENT;
            }
            unsigned long Elapsed = _GetElapsed();
            pOutBuffer->Copy((Byte *)&Elapsed,4);
            pOutBuffer->SetUsed(4);
            break;
        }
        case 13://set alarm date and time
        {
            if (inBuffer.GetCapacity() < 28) {
                return E_INVALID_ARGUMENT;
            }
            int * p = (int *)inBuffer.GetPayload();
            return setAlarmDateTime(p);
        }
        case 14://get alarm date and time
        {
        	if (pOutBuffer == NULL || pOutBuffer->GetCapacity() < 28) {
            	return E_INVALID_ARGUMENT;
            }
            return GetAlarmDateTime(pOutBuffer);
        }
        case 15://get rtc date and time
        {	if (pOutBuffer == NULL || pOutBuffer->GetCapacity() < 28) {
            	return E_INVALID_ARGUMENT;
            }
            return GetRTCDateTime(pOutBuffer);
        }
        default :break;
    }
    return NOERROR;
}

ECode CRTC::RTCEventThread()
{
    WaitResult wr;
    EmIsrParameter param;
    RTCATime rtcTime;
    PackTime t;
    while (1) {
        m_RTCEvent.Wait(&wr, NULL);
        kprintf("-------------on Alarm--------------\n");
        memset(&param, 0, sizeof(EmIsrParameter));
    	g_pNURTCDriver->GetRTCTime(&rtcTime);
    	t.uYear = rtcTime.year;
    	t.uMonth = rtcTime.month;
    	t.uDay = rtcTime.day;
    	t.uHour = rtcTime.hour;
    	t.uMinute = rtcTime.minute;
    	t.uSecond = rtcTime.second;
    	memcpy(&param, &t, sizeof(PackTime));
        DzSyncSystemTime();
        EmPostEventByIsr(113, &param);
    }
    return NOERROR;
}

ECode RTCThreadRoutine(void *arg)
{
    g_pRTC->RTCEventThread();
    return NOERROR;
}

ECode SyncSystimeRoutine(void *arg)
{
    WaitResult result;
    while (1) {
        DzSleep(60 * 100, &result);
        DzSyncSystemTime();
    }
}

ECode CreateRTCSyncTimerThread()
{
    ECode ec;
    ec = DzCreateKernelThread(SyncSystimeRoutine,
        (PVoid)NULL, CreateThreadFlag_System, ThreadPriorityRank_Normal, NULL);
    if (FAILED(ec)) {
        kprintf("unable to create syncTimer thread ec : %08x\n", ec);
        return ec;
    }
    kprintf("Create SyncTimer Thread Succeeded!\n");
    return ec;
}

ECode CreateRTCThread()
{
    ECode ec;
    ec = DzCreateKernelThread(RTCThreadRoutine,
        (PVoid)NULL, CreateThreadFlag_System, ThreadPriorityRank_Normal, NULL);
    if (FAILED(ec)) {
        kprintf("unable to create rtc thread ec : %08x\n", ec);
        return ec;
    }
    kprintf("Create rtc Management Thread Succeeded!\n");
    return ec;
}

//void CancelRTCSyncTimer()
//{
//    g_pRTC->m_pSyncTimer->Cancel();
//}

//void RestartRTCSyncTimer()
//{
//    g_pRTC->m_pSyncTimer->Restart(60 * 100);
//}
EXTERN IDeviceDriver * CDECL CreateRTC(uint_t uDeviceNo, void *pvParameter)
{
   	g_pNURTCDriver = nu_GetRTCDriverAPI();
	if (NULL == g_pNURTCDriver) {
		kprintf("RTC Init Failed! %S, %d \n", __FILE__, __LINE__);
		return NULL;
	}

    g_pRTC = new CRTC;
    if (NULL == g_pRTC) {
    	kprintf("RTC Init Failed!\n");
    	return NULL;
    }

    g_ostDelta = _GetElapsed();

    g_pNURTCDriver->SetEventAddress((UInt32)&(g_pRTC->m_RTCEvent));

    CreateRTCThread();

    CreateRTCSyncTimerThread();

    return g_pRTC;
}


